package buildinjava.io;

import com.google.common.collect.Lists;
import java.io.FileFilter;
import java.util.List;

/**
 * Builds a FileFilter.
 *
 * @author Gili Tzabari
 */
public final class FileFilterBuilder
{
	private final List<FileFilter> accept = Lists.newArrayList();
	private final List<FileFilter> reject = Lists.newArrayList();

	/**
	 * Creates a new FileFilterBuilder.
	 *
	 * @param filter indicates what files to accept
	 */
	public FileFilterBuilder(FileFilter filter)
	{
		accept.add(filter);
	}

	/**
	 * Adds a file to the list of acceptable files.
	 *
	 * @param wildcard a wildcard string describing the files to accept
	 * @return the FileFilterBuilder
	 * @see WildcardFileFilter
	 */
	public FileFilterBuilder addFile(String wildcard)
	{
		accept.add(FileFilters.intersection(new WildcardFileFilter(wildcard), FileFilters.isFile()));
		return this;
	}

	/**
	 * Adds a file to the list of acceptable files.
	 *
	 * @param wildcard a wildcard string describing the file to reject
	 * @return the FileFilterBuilder
	 * @see WildcardFileFilter
	 */
	public FileFilterBuilder removeFile(String wildcard)
	{
		reject.add(FileFilters.negation(FileFilters.intersection(new WildcardFileFilter(wildcard),
			FileFilters.isFile())));
		return this;
	}

	/**
	 * Adds a directory to the list of acceptable files.
	 *
	 * @param wildcard a wildcard string describing the directories to accept
	 * @return the FileFilterBuilder
	 * @see WildcardFileFilter
	 */
	public FileFilterBuilder addDirectory(String wildcard)
	{
		accept.add(FileFilters.intersection(new WildcardFileFilter(wildcard), FileFilters.isDirectory()));
		return this;
	}

	/**
	 * Removes a directory from the list of acceptable files.
	 *
	 * @param wildcard a wildcard string describing the directories to reject
	 * @return the FileFilterBuilder
	 * @see WildcardFileFilter
	 */
	public FileFilterBuilder removeDirectory(String wildcard)
	{
		reject.add(FileFilters.negation(FileFilters.intersection(new WildcardFileFilter(wildcard),
			FileFilters.isDirectory())));
		return this;
	}

	/**
	 * Returns the FileFilter.
	 *
	 * @return the FileFilter
	 */
	public FileFilter build()
	{
		List<FileFilter> intersections = Lists.newArrayList();
		if (!accept.isEmpty())
			intersections.add(FileFilters.union(accept.toArray(new FileFilter[0])));
		intersections.addAll(reject);
		return FileFilters.intersection(intersections.toArray(new FileFilter[0]));
	}
}
